package com.social.utils;

import com.rabbitmq.client.Channel;
import com.social.pojo.dto.SmsDTO;
import com.social.pojo.propertie.SmsProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;


import static com.social.constant.RabbitMqConstants.*;

/**
 * @author zero
 * @version 1.0
 * @project demo
 * @description 消息队列监听器
 * @date 2022/12/16 13:28:50
 */
@Component
@Slf4j
@EnableConfigurationProperties(SmsProperties.class)
public class SmsReceiver{
    enum Action {
        //处理成功
        SUCCESS,
        //可以重试的错误，消息重回队列
        RETRY,
        //无需重试的错误，拒绝消息，并从队列中删除
        REJECT
    }
    @Resource
    private SmsUtil smsUtil;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = QUEUE_SMS_ITEM, durable = "true"),
            exchange = @Exchange(value = EXCHANGE_TOPIC_SMS),
            key = {ROUTING_SMS_ITEM}
    ))
    @RabbitHandler
    public void send(SmsDTO smsDTO, Message message, Channel channel) throws IOException {
        long tag = message.getMessageProperties().getDeliveryTag();
        Action action = Action.SUCCESS;
        try {
            System.out.println("消费者RabbitDemoConsumer从RabbitMQ服务端消费消息：" + smsDTO);
            Map<String, Object> map = new HashMap<>();
            map.put("code", smsDTO.getMessage());
            smsUtil.send(map,smsDTO.getMobile());
        } catch (IllegalArgumentException e1) {
            e1.printStackTrace();
            //根据异常的类型判断，设置action是可重试的，还是无需重试的
            action = Action.RETRY;
        } catch (Exception e2) {
            //打印异常
            e2.printStackTrace();
            //根据异常的类型判断，设置action是可重试的，还是无需重试的
            action = Action.REJECT;
        } finally {
            try {
                if (action == Action.SUCCESS) {
                    //multiple 表示是否批量处理。true表示批量ack处理小于tag的所有消息。false则处理当前消息
                    channel.basicAck(tag, false);
                } else if (action == Action.RETRY) {
                    //Nack，拒绝策略，消息重回队列
                    channel.basicNack(tag, false, true);
                } else {
                    //Nack，拒绝策略，并且从队列中删除
                    channel.basicNack(tag, false, false);
                }
                channel.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

